package com.google.code.etrclient.helper;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.apache.http.HttpResponse;
import org.htmlcleaner.CleanerProperties;
import org.htmlcleaner.CompactXmlSerializer;
import org.htmlcleaner.HtmlCleaner;
import org.htmlcleaner.TagNode;
import org.htmlcleaner.XPatherException;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import com.google.code.etrclient.pojo.Course;
import com.google.code.etrclient.xml.XMLCoursesParseHandler;

public class Helper {
  /**
   * Converts an HttpResponse into a one-line string
   * 
   * @param response The HttpResponse to convert
   * @return The string that is decoded from the HttpResponse
   */
  public static String decodeResponse(HttpResponse response) {
    StringBuilder res = new StringBuilder();
    String line = "";
    
    try {
      BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
      while ((line = rd.readLine()) != null) {
        res.append(line);
      }
    } catch (IllegalStateException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }
    
    return res.toString();
  }
  
  /**
   * Cleans the dirty, poorly formatted HTML and truncates it to the table that contains the courses using HTMLCleaner and XPATH
   * 
   * @param dirtyHtml The HTML to clean in a 
   * @return A string containing the HTML code of the table with the courses
   */
  public static String cleanAndTruncCoursesHtml (String dirtyHtml) {
    String res = "";
    
    try {
      CleanerProperties props = new CleanerProperties();
      props.setTranslateSpecialEntities(true);
      props.setTransResCharsToNCR(true);
      props.setOmitComments(true);
      props.setOmitDoctypeDeclaration(true);
      props.setOmitXmlDeclaration(true);
      HtmlCleaner cleaner = new HtmlCleaner(props);
      
      TagNode node = cleaner.clean(dirtyHtml);
      Object[] table_object = node.evaluateXPath("//table[@id='kurzList']");
      if (table_object.length > 0) {
        TagNode table_node = (TagNode)table_object[0];
        ByteArrayOutputStream writer = new ByteArrayOutputStream();
        new CompactXmlSerializer(props).writeToStream(table_node, writer);
        res = writer.toString();
      }
    } catch (IOException e) {
      e.printStackTrace();
    } catch (XPatherException e) {
      e.printStackTrace();
    }
    
    return res;
  }
  
  /**
   * Creates Course type objects from XML/HTML
   * 
   * @param xml The XML/HTML string to parse
   * @return A list containing Course objects
   */
  public static ArrayList<Course> parseCoursesXMLtoPOJO(String xml) {
    ArrayList<Course> courses = new ArrayList<Course>();
    
    try {
      SAXParserFactory parserFactory = SAXParserFactory.newInstance();
      SAXParser parser = parserFactory.newSAXParser();
      XMLReader reader = parser.getXMLReader();
      XMLCoursesParseHandler parseHandler = new XMLCoursesParseHandler();
      
      reader.setContentHandler(parseHandler);
      reader.parse(new InputSource(new StringReader(xml)));
      courses = parseHandler.getParsedData();
      
    } catch (ParserConfigurationException e) {
      e.printStackTrace();
    } catch (SAXException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }
      
    return courses; 
  }
}
